/**
 *
 */
package com.angel.data.generator.builders.impl;

import java.lang.reflect.Method;
import java.util.Collection;

import com.angel.common.helpers.AnnotationHelper;
import com.angel.common.helpers.ReflectionHelper;
import com.angel.data.generator.annotations.importFileProcessorRunner.ImportFileProcessorRunnerBuilder;
import com.angel.data.generator.annotations.inputStream.InputStreamBuilder;
import com.angel.data.generator.base.DataGeneratorRunner;
import com.angel.data.generator.base.impl.DataGeneratorAnnotationRunner;
import com.angel.data.generator.builders.DataGeneratorRunnerBuilder;
import com.angel.data.generator.checkers.DataGeneratorChecker;
import com.angel.data.generator.interfaces.impl.AnnotationDataGenerator;
import com.angel.data.generator.preProcess.PreProcessStrategy;
import com.angel.data.generator.validators.impl.GeneratorAnnotationClassValidator;
import com.angel.data.generator.validators.impl.ImporFileProcessorRunnerMethodValidator;
import com.angel.data.generator.validators.impl.InjectFieldAnnotationValidator;
import com.angel.data.generator.validators.impl.OnlyOneImportFileProcessorRunnerBuilderAnnotationValidator;
import com.angel.data.generator.validators.impl.OnlyOneInputStreamBuilderAnnotationValidator;

/**
 *
 * @author William
 * @since 21/August/2009.
 *
 */
public class DataGeneratorAnnotationRunnerBuilder extends DataGeneratorRunnerBuilder{

	private DataGeneratorAnnotationRunner annotationRunner;

    public DataGeneratorAnnotationRunnerBuilder(){
        super();
        annotationRunner = new DataGeneratorAnnotationRunner();
        this.initializeValidators();
    }

    public DataGeneratorAnnotationRunnerBuilder(Collection<DataGeneratorChecker> dataGeneratorCheckers){
        super(dataGeneratorCheckers);
        annotationRunner = new DataGeneratorAnnotationRunner();
        this.initializeValidators();
    }

    public DataGeneratorAnnotationRunnerBuilder(Collection<DataGeneratorChecker> dataGeneratorCheckers, PreProcessStrategy preProcessStrategy){
        super(dataGeneratorCheckers, preProcessStrategy);
        annotationRunner = new DataGeneratorAnnotationRunner();

    }

    protected void initializeValidators(){
    	super.addDataGeneratorBuilderValidator(new GeneratorAnnotationClassValidator());// Object class check: Check that object class have Generator annotation.
    	super.addDataGeneratorBuilderValidator(new OnlyOneImportFileProcessorRunnerBuilderAnnotationValidator());//Check class have one and only one imporFileProcessorRunnerBuilderMethod annotation.
    	super.addDataGeneratorBuilderValidator(new OnlyOneInputStreamBuilderAnnotationValidator());//Check class have one and only one inputStreamBuilderMethod annotation.
    	super.addDataGeneratorBuilderValidator(new ImporFileProcessorRunnerMethodValidator());
    	super.addDataGeneratorBuilderValidator(new InjectFieldAnnotationValidator());
    }

    public DataGeneratorRunner buildDataGeneratorRunner(){
    	annotationRunner.addDataGeneratorCheckers(super.getCheckerRunner().getCheckers());
    	annotationRunner.setPreProcessStrategy(super.getPreProcessStrategy());
    	return annotationRunner;
    }

    public <T> void addDataGeneratorClass(Class<T> dataGeneratorClass){
    	this.validateDataGeneratorClass(dataGeneratorClass);
    	Object objectDataGenerator = ReflectionHelper.createObject(dataGeneratorClass);
    	Method processorRunnerBuilderMethod = AnnotationHelper.getMethodWithAnnotation(dataGeneratorClass, ImportFileProcessorRunnerBuilder.class);
    	Method inputStreamBuilderMethod = AnnotationHelper.getMethodWithAnnotation(dataGeneratorClass, InputStreamBuilder.class);
    	AnnotationDataGenerator annotationDataGenerator = new AnnotationDataGenerator(objectDataGenerator, processorRunnerBuilderMethod, inputStreamBuilderMethod);
    	this.addDataGenerator(annotationDataGenerator);
    }
    
    protected void addDataGenerator(AnnotationDataGenerator annotationDataGenerator){
    	annotationRunner.addDataGenerator(annotationDataGenerator);
    }

	/**
	 * @return the annotationRunner
	 */
	protected DataGeneratorAnnotationRunner getAnnotationRunner() {
		return annotationRunner;
	}

	/**
	 * @param annotationRunner the annotationRunner to set
	 */
	protected void setAnnotationRunner(
			DataGeneratorAnnotationRunner annotationRunner) {
		this.annotationRunner = annotationRunner;
	}
}
